home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / c_lang / bituudec.c < prev    next >
C/C++ Source or Header  |  1987-12-23  |  7KB  |  274 lines

  1. /* bituudec.c */
  2.  
  3. /* Exit status values:
  4.    1    Unable to open input file.
  5.    2    Removed, used to indicate more than one argument.
  6.    3    No begin line, probably not a uuencoded file.
  7.    4    Unable to write output file.
  8.    5    Missing an end line, file may be truncated?
  9.   10    Short file, EOF reached while decoding.
  10. */
  11.  
  12. /* Modified version of uudecode by Mark S. Zinzow
  13.    in IBM C or MSC V. 2   use
  14.    clink bituudec ssetargv;
  15.    to get DOS command line wildcard processing  */
  16.  
  17. #ifndef lint
  18. static char sccsid[] = "@(#)bituudecode.c       6.0 (Berkeley & M.S.Z.) 3/22/87"
  19. #endif
  20.  
  21. /*
  22.  * uudecode [input]
  23.  *
  24.  * create the specified file, decoding as you go.
  25.  * used with uuencode.
  26.  */
  27. #include <stdio.h>
  28. #ifndef MSDOS
  29. #include <pwd.h>
  30. #endif
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33.  
  34. /* single character decode */
  35. #define DEC(c)  (((c) - ' ') & 077)
  36.  
  37. main(argc, argv)
  38. char **argv;
  39. {
  40.         FILE *in;
  41.  
  42. /* M.S.Z. 3/22/87
  43.    The following code block was deleted to support decoding of multiple
  44.    files with the use of wild cards or several command line filenames.
  45.    Part of the main line was moved to the function uufile with the
  46.    appropriate changes for repeating for several files.
  47. */
  48.  
  49.         /* optional input arg M.S.Z why only one file?
  50.         if (argc > 1) {
  51.                 if ((in = fopen(argv[1], "r")) == NULL) {
  52.                         perror(argv[1]);
  53.                         exit(1);
  54.                 }
  55.                 argv++; argc--;
  56.         } else
  57.                 in = stdin;
  58.  
  59.         if (argc != 1) {
  60.                 printf("Usage: uudecode [infile]\n");
  61.                 exit(2);
  62.         }  */
  63.  
  64.         if (argc == 1)  /* no args; copy standard input */
  65.                 uufile(stdin);
  66.         else
  67.                 while (--argc > 0)
  68.                         if ((in = fopen(*++argv, "r")) == NULL) {
  69.                                 perror(*argv);
  70.                                 exit(1);
  71.                         } else {
  72.                                 uufile(in);
  73.                                 fclose(in);
  74.                                 }
  75.         exit(0);
  76. }
  77.  
  78. uufile(in)  /* Process one input file M.S.Z. */
  79. FILE *in;
  80. {
  81.         FILE *out;
  82.         struct stat sbuf;
  83.         int mode, filect=0;
  84.         char dest[128];
  85.         char buf[80];
  86.  
  87.   while ( !feof(in) ) {  /* added while and filect for status */
  88.         /* search for header line */
  89.         for (;;) {
  90.                 if (fgets(buf, sizeof buf, in) == NULL) {
  91.                         if (filect < 1) {
  92.                                 fprintf(stderr, "No begin line\n");
  93.                                 exit(3);
  94.                                 }
  95.                         else
  96.                         return;
  97.                 }
  98.                 if (strncmp(buf, "begin ", 6) == 0)
  99.                         break;
  100.         }
  101.         sscanf(buf, "begin %o %s", &mode, dest);
  102.         fprintf(stderr,
  103.         "Processing file %d \"%s\", in current source file.\n",
  104.         ++filect,dest);
  105.  
  106.         /* handle ~user/file format */
  107. #ifndef MSDOS
  108.         if (dest[0] == '~') {
  109.                 char *sl;
  110.                 struct passwd *getpwnam();
  111.                 char *index();
  112.                 struct passwd *user;
  113.                 char dnbuf[100];
  114.  
  115.                 sl = index(dest, '/');
  116.                 if (sl == NULL) {
  117.                         fprintf(stderr, "Illegal ~user\n");
  118.                         exit(3);
  119.                 }
  120.                 *sl++ = 0;
  121.                 user = getpwnam(dest+1);
  122.                 if (user == NULL) {
  123.                         fprintf(stderr, "No such user as %s\n", dest);
  124.                         exit(4);
  125.                 }
  126.                 strcpy(dnbuf, user->pw_dir);
  127.                 strcat(dnbuf, "/");
  128.                 strcat(dnbuf, sl);
  129.                 strcpy(dest, dnbuf);
  130.         }
  131. #endif
  132.  
  133.         /* create output file */
  134. #ifdef MSDOS
  135.         /* binary output file */
  136.         out = fopen(dest, "wb");
  137. #else
  138.         out = fopen(dest, "w");
  139. #endif
  140.         if (out == NULL) {
  141.                 perror(dest);
  142.                 exit(4);
  143.         }
  144.         chmod(dest, mode);
  145.  
  146.         decode(in, out);
  147.  
  148.         if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  149.                 fprintf(stderr, "No end line\n");
  150.                 exit(5);
  151.         }
  152.         fclose(out);
  153.   }
  154. }
  155.  
  156. /*
  157.  * copy from in to out, decoding as you go along.
  158.  */
  159. decode(in, out)
  160. FILE *in;
  161. FILE *out;
  162. {
  163.         char buf[80];
  164.         char *bp;
  165.         int n,j,k,l;    /* M.S.Z.  added jkl for a counters in padding spaces */
  166.  
  167.         for (;;) {
  168.                 /* for each input line */
  169.                 if (fgets(buf, sizeof buf, in) == NULL) {
  170.                         printf("Short file\n");
  171.                         exit(10);
  172.                 }
  173.                 n = DEC(buf[0]);
  174.  
  175. /* was
  176.                 if (n <= 0)
  177.                         break;
  178. */
  179.                 if (buf[0] <= ' ')
  180.                         break;
  181. /*  M.S.Z.  What good does it do to test n<0 when in DEC the sign bits are
  182.             masked off?
  183.             This seems to allow us to just ignore blank lines.
  184.             A blank line (just \n) before the final end used to cause
  185.             a short file error message, now that's not a problem.
  186.  
  187. Next I'm adding a kludge to tack trailing spaces back on the input lines:  */
  188.  
  189.                 j = strlen(buf);
  190.                 k =  n*4/3 + 2 ; /* add 1 for \n and 1 for the first count char
  191.                 if ( j < k )
  192.                         for( l=j-1 ; l < k && l < sizeof buf ; l++ )  buf[l] = '
  193.                         /* Ignore that this changes the \n to a ' ';
  194.                            that doesn't hurt. M.S.Z. */
  195.  
  196. /* M.S.Z. end kludge */
  197.  
  198.                 bp = &buf[1];
  199.                 while (n > 0) {
  200.                         outdec(bp, out, n);
  201.                         bp += 4;
  202.                         n -= 3;
  203.                 }
  204.         }
  205. }
  206.  
  207. /*
  208.  * output a group of 3 bytes (4 input characters).
  209.  * the input chars are pointed to by p, they are to
  210.  * be output to file f.  n is used to tell us not to
  211.  * output all of them at the end of the file.
  212.  */
  213. outdec(p, f, n)
  214. char *p;
  215. FILE *f;
  216. {
  217.         int c1, c2, c3;
  218.  
  219.         c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  220.         c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  221.         c3 = DEC(p[2]) << 6 | DEC(p[3]);
  222.         if (n >= 1)
  223.                 putc(c1, f);
  224.         if (n >= 2)
  225.                 putc(c2, f);
  226.         if (n >= 3)
  227.                 putc(c3, f);
  228.  
  229. /*  M.S.Z.  Another problem.  Nobody notices when the disk is full! */
  230.         if (ferror(f))  {
  231.                 perror("Write error");
  232.                 exit(4);
  233.                 }
  234. /*  M.S.Z. end another hack */
  235.  
  236. }
  237.  
  238.  
  239. /* fr: like read but stdio */
  240. int
  241. fr(fd, buf, cnt)
  242. FILE *fd;
  243. char *buf;
  244. int cnt;
  245. {
  246.         int c, i;
  247.  
  248.         for (i=0; i<cnt; i++) {
  249.                 c = getc(fd);
  250.                 if (c == EOF)
  251.                         return(i);
  252.                 buf[i] = c;
  253.         }
  254.         return (cnt);
  255. }
  256.  
  257. /*
  258.  * Return the ptr in sp at which the character c appears;
  259.  * NULL if not found
  260.  */
  261.  
  262. #define NULL    0
  263.  
  264. char *
  265. index(sp, c)
  266. register char *sp, c;
  267. {
  268.         do {
  269.                 if (*sp == c)
  270.                         return(sp);
  271.         } while (*sp++);
  272.         return(NULL);
  273. }
  274.